package com.ev.asl.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ev.asl.constant.AslConstant;
import com.ev.asl.dao.MoldingProductionInstructionDao;
import com.ev.asl.domain.MoldingProductionInstructionDO;
import com.ev.asl.service.MoldingProductionInstructionService;
import com.ev.custom.dao.MaterielDao;
import com.ev.custom.domain.MaterielDO;
import com.ev.framework.utils.DateUtils;
import com.ev.mes.dao.BomDao;
import com.ev.mes.dao.BomDetailDao;
import com.ev.mes.domain.BomDO;
import com.ev.mes.domain.BomDetailDO;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 姚家乐
 * @since 2021/5/26 13:03
 */
@Service
public class MoldingProductionInstructionServiceImpl implements
        MoldingProductionInstructionService {

    @Autowired
    private MoldingProductionInstructionDao dao;

    @Autowired
    private BomDao                          bomDao;

    @Autowired
    private BomDetailDao                    bomDetailDao;

    @Autowired
    private MaterielDao                     materielDao;

    /**
     * 新增保存
     * @param entity
     * @return
     */
    @Override
    public Integer save(MoldingProductionInstructionDO entity) {
        entity.setDelFlag(AslConstant.NO);
        entity.setHaveFirstCheck(AslConstant.NO);
        entity.setStatus(AslConstant.MoldingProductionInstructionStatus.PLAN.getType());
        return dao.save(entity);
    }

    @Override
    public MoldingProductionInstructionDO get(Long id) {
        return dao.get(id);
    }

    /**
     * 单个查询详情
     * @param id
     * @return
     */
    @Override
    public Map<String, Object> getDetailInfo(Long id) {
        Map<String, Object> map = dao.getDetailInfo(id);

        map.put("indicateDate", DateUtils.format((Date) map.get("indicateDate")));
        map.put("startDate", DateUtils.format((Date) map.get("startDate"),DateUtils.DATE_TIME_PATTERN));
        map.put("endDate", DateUtils.format((Date) map.get("endDate"),DateUtils.DATE_TIME_PATTERN));

        //获取bom信息
        BomDO bomDO = bomDao.get((Long) map.get("bomId"));

        MaterielDO materiel = materielDao.get((Long) map.get("materielId"));
        //容量
        map.put("productCapacity",materiel.getVolume());
        //重量
        map.put("weight",materiel.getNetWeight());
        JSONObject jsonObject = ObjectUtils.isEmpty(map.get("rawMaterialRatio")) ? new JSONObject() : JSON.parseObject(map.get("rawMaterialRatio").toString());
        map.put("rawMaterialRatio",jsonObject);
        //品名
        map.put("materielName",materiel.getName());

        Map<String, Object> params = Maps.newHashMapWithExpectedSize(2);

        params.put("bomId", bomDO.getId());

        // 一级
        List<BomDetailDO> bomDetailDOSOne = bomDetailDao.list(params);
        //判断一级原料是否自制件，是的话，就根据物料编号去bom单中查询指定的一级原料的子bom
        List<Long> parentMaterielIds = bomDetailDOSOne.stream().filter(e->AslConstant.TWO.equals(e.getMaterielType())).map(BomDetailDO::getMaterielId).collect(Collectors.toList());
        //所有物料的ids
        List<Long> materielIds = bomDetailDOSOne.stream().filter(e->!AslConstant.TWO.equals(e.getMaterielType())).map(BomDetailDO::getMaterielId).collect(Collectors.toList());



        //二级bomId
        params.remove("bomId");
        //二级bom
        List<BomDO> twoBomDOS = null;
        //二级bom子原料
        List<BomDetailDO> bomDetailDOSTwo = null;
        if (!CollectionUtils.isEmpty(parentMaterielIds)) {
            params.put("materielIds", parentMaterielIds);
            //二级bom
            twoBomDOS = bomDao.list(params);
            List<Long> twoBomIds = twoBomDOS.stream().map(BomDO::getId)
                    .collect(Collectors.toList());
            params.remove("materielIds");
            params.put("bomIds", twoBomIds);
            //二级bom子原料
            bomDetailDOSTwo = bomDetailDao.list(params);
            materielIds.addAll(bomDetailDOSTwo.stream().map(BomDetailDO::getMaterielId).collect(Collectors.toList()));
        }

        params.remove("bomIds");
        params.put("ids", materielIds);
        List<MaterielDO> materielDOList = materielDao.listTwo(params);

        List<Map<String, Object>> mapList = new ArrayList<>();

        //求原料的总用量
        BigDecimal totalAmount = BigDecimal.ZERO;
        List<BomDetailDO> bomDetailDOS = new ArrayList<>();
        bomDetailDOS.addAll(bomDetailDOSOne.stream().filter(e -> !AslConstant.TWO.equals(e.getMaterielType()))
                .collect(Collectors.toList()));
        if (!CollectionUtils.isEmpty(bomDetailDOSTwo)){
            bomDetailDOS.addAll(bomDetailDOSTwo);
        }
        for (BomDetailDO detailDO : bomDetailDOS) {
            totalAmount = totalAmount.add(
                    detailDO.getStandardCount() != null ? detailDO.getStandardCount() : BigDecimal.ZERO)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
        }

        BigDecimal proportion = BigDecimal.ZERO;

        for (BomDetailDO detailDO : bomDetailDOSOne) {
            Map<String, Object> objectMap = new HashMap<>();
            //无下级子物料时
            if (!AslConstant.TWO.equals(detailDO.getMaterielType())) {
                for (MaterielDO materielDO : materielDOList) {
                    if (detailDO.getMaterielId().equals(materielDO.getId())) {
                        //层次
                        objectMap.put("level", materielDO.getName());
                        //原料编码
                        objectMap.put("rawMaterialCode", materielDO.getSerialNo());
                        //原料名称
                        objectMap.put("rawMaterialName", materielDO.getName());
                        //规格型号
                        objectMap.put("specification", materielDO.getSpecification());
                        //计量单位
                        objectMap.put("unitUom", materielDO.getUnitUom());
                        objectMap.put("unitUomName", materielDO.getUnitUomName());
                        //用量
                        objectMap.put("standardCount", detailDO.getStandardCount());
                        proportion = detailDO.getStandardCount()
                                .divide(totalAmount, BigDecimal.ROUND_HALF_UP)
                                .multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
                        //比例
                        objectMap.put("proportion", proportion);
                        objectMap.put("cbcount", AslConstant.ONE);
                        objectMap.put("cbaa", AslConstant.ZERO);
                        mapList.add(objectMap);
                    }

                }
            }
            if (AslConstant.TWO.equals(detailDO.getMaterielType())) {
                if (!CollectionUtils.isEmpty(twoBomDOS)) {
                    for (BomDO bomDO1 : twoBomDOS) {
                        if (detailDO.getMaterielId().equals(bomDO1.getMaterielId())) {
                            int cbcount = AslConstant.ZERO;
                            if (!CollectionUtils.isEmpty(bomDetailDOSTwo)) {
                                for (BomDetailDO detailDO1 : bomDetailDOSTwo) {

                                    if (bomDO1.getId().equals(detailDO1.getBomId())) {
                                        for (MaterielDO materielDO : materielDOList) {
                                            if (bomDO1.getMaterielId().equals(materielDO.getId())) {
                                                objectMap.put("level", materielDO.getName());
                                            }
                                            if (detailDO1.getMaterielId()
                                                    .equals(materielDO.getId())) {
                                                //原料编码
                                                objectMap.put("rawMaterialCode",
                                                        materielDO.getSerialNo());
                                                //原料名称
                                                objectMap.put("rawMaterialName",
                                                        materielDO.getName());
                                                //规格型号
                                                objectMap.put("specification",
                                                        materielDO.getSpecification());
                                                //计量单位
                                                objectMap.put("unitUom", materielDO.getUnitUom());
                                            }
                                        }
                                        //比例
                                        cbcount = cbcount + 1;
                                        objectMap.put("cbaa", cbcount);
                                        //用量
                                        objectMap.put("standardCount",
                                                detailDO1.getStandardCount());
                                        proportion = detailDO1.getStandardCount()
                                                .divide(totalAmount, BigDecimal.ROUND_HALF_UP)
                                                .multiply(new BigDecimal("100"))
                                                .setScale(2, BigDecimal.ROUND_HALF_UP);

                                        objectMap.put("proportion", proportion);
                                    }
                                }
                                objectMap.put("cbcount", cbcount);
                                mapList.add(objectMap);
                            }

                        }
                    }
                }

            }
        }

        Map<String,Object> map1 = new HashMap<>();
        map1.put("bomList",mapList);
        map1.put("ylcount",mapList.size());
        map.put("bom",map1);
        map.put("bomNo",bomDO.getSerialno());
        return map;
    }
    /**
     * 单个查询详情
     * @param id
     * @return
     */
    @Override
    public Map<String, Object> getDetail(Long id) {
        Map<String, Object> map = dao.getDetail(id);
        return map;
    }

    /**
     * 单个查询详情
     * @param id
     * @return
     */
    @Override
    public Map<String, Object> getDetailInfoTwo(Long id) {
        Map<String, Object> map = dao.getDetailInfo(id);

        map.put("indicateDate", DateUtils.format((Date) map.get("indicateDate")));

        //获取bom信息
        BomDO bomDO = bomDao.get((Long) map.get("bomId"));

        MaterielDO materiel = materielDao.get((Long) map.get("materielId"));
        //容量
        map.put("productCapacity",materiel.getVolume());
        //重量
        map.put("weight",materiel.getNetWeight());
        //品名
        map.put("materielName",materiel.getName());

        Map<String, Object> params = Maps.newHashMapWithExpectedSize(2);

        params.put("bomId", bomDO.getId());

        // 一级
        List<BomDetailDO> bomDetailDOSOne = bomDetailDao.list(params);
        //判断一级原料是否自制件，是的话，就根据物料编号去bom单中查询指定的一级原料的子bom
        List<Long> parentMaterielIds = bomDetailDOSOne.stream().filter(e->AslConstant.TWO.equals(e.getMaterielType())).map(BomDetailDO::getMaterielId).collect(Collectors.toList());
        //所有物料的ids
        List<Long> materielIds = bomDetailDOSOne.stream().filter(e->!AslConstant.TWO.equals(e.getMaterielType())).map(BomDetailDO::getMaterielId).collect(Collectors.toList());



        //二级bomId
        params.remove("bomId");
        //二级bom
        List<BomDO> twoBomDOS = null;
        //二级bom子原料
        List<BomDetailDO> bomDetailDOSTwo = null;
        if (!CollectionUtils.isEmpty(parentMaterielIds)) {
            params.put("materielIds", parentMaterielIds);
            //二级bom
            twoBomDOS = bomDao.list(params);
            List<Long> twoBomIds = twoBomDOS.stream().map(BomDO::getId)
                    .collect(Collectors.toList());
            params.remove("materielIds");
            params.put("bomIds", twoBomIds);
            //二级bom子原料
            bomDetailDOSTwo = bomDetailDao.list(params);
            materielIds.addAll(bomDetailDOSTwo.stream().map(BomDetailDO::getMaterielId).collect(Collectors.toList()));
        }

        params.remove("bomIds");
        params.put("ids", materielIds);
        List<MaterielDO> materielDOList = materielDao.listTwo(params);

        List<Map<String, Object>> mapList = new ArrayList<>();

        //求原料的总用量
        BigDecimal totalAmount = BigDecimal.ZERO;
        List<BomDetailDO> bomDetailDOS = new ArrayList<>();
        bomDetailDOS.addAll(bomDetailDOSOne.stream().filter(e -> !AslConstant.TWO.equals(e.getMaterielType()))
                .collect(Collectors.toList()));
        if (!CollectionUtils.isEmpty(bomDetailDOSTwo)){
            bomDetailDOS.addAll(bomDetailDOSTwo);
        }
        for (BomDetailDO detailDO : bomDetailDOS) {
            totalAmount = totalAmount.add(
                    detailDO.getStandardCount() != null ? detailDO.getStandardCount() : BigDecimal.ZERO)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
        }

        BigDecimal proportion = BigDecimal.ZERO;

//        for (BomDetailDO detailDO : bomDetailDOSOne) {
//            Map<String, Object> objectMap = new HashMap<>();
//            //无下级子物料时
//            if (!AslConstant.TWO.equals(detailDO.getMaterielType())) {
//                for (MaterielDO materielDO : materielDOList) {
//                    if (detailDO.getMaterielId().equals(materielDO.getId())) {
//                        //层次
//                        objectMap.put("level", materielDO.getName());
//                        //原料编码
//                        objectMap.put("rawMaterialCode", materielDO.getSerialNo());
//                        //原料名称
//                        objectMap.put("rawMaterialName", materielDO.getName());
//                        //规格型号
//                        objectMap.put("specification", materielDO.getSpecification());
//                        //计量单位
//                        objectMap.put("unitUom", materielDO.getUnitUom());
//                        //用量
//                        objectMap.put("standardCount", detailDO.getStandardCount());
//                        proportion = detailDO.getStandardCount()
//                                .divide(totalAmount, BigDecimal.ROUND_HALF_UP)
//                                .multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
//                        //比例
//                        objectMap.put("proportion", proportion);
//                        objectMap.put("cbcount", AslConstant.ONE);
//                        objectMap.put("cbaa", AslConstant.ZERO);
//                        mapList.add(objectMap);
//                    }
//
//                }
//            }
//            if (AslConstant.TWO.equals(detailDO.getMaterielType())) {
//                if (!CollectionUtils.isEmpty(twoBomDOS)) {
//                    for (BomDO bomDO1 : twoBomDOS) {
//                        if (detailDO.getMaterielId().equals(bomDO1.getMaterielId())) {
//                            int cbcount = AslConstant.ZERO;
//                            if (!CollectionUtils.isEmpty(bomDetailDOSTwo)) {
//                                for (BomDetailDO detailDO1 : bomDetailDOSTwo) {
//
//                                    if (bomDO1.getId().equals(detailDO1.getBomId())) {
//                                        for (MaterielDO materielDO : materielDOList) {
//                                            if (bomDO1.getMaterielId().equals(materielDO.getId())) {
//                                                objectMap.put("level", materielDO.getName());
//                                            }
//                                            if (detailDO1.getMaterielId()
//                                                    .equals(materielDO.getId())) {
//                                                //原料编码
//                                                objectMap.put("rawMaterialCode",
//                                                        materielDO.getSerialNo());
//                                                //原料名称
//                                                objectMap.put("rawMaterialName",
//                                                        materielDO.getName());
//                                                //规格型号
//                                                objectMap.put("specification",
//                                                        materielDO.getSpecification());
//                                                //计量单位
//                                                objectMap.put("unitUom", materielDO.getUnitUom());
//                                            }
//                                        }
//                                        //比例
//                                        cbcount = cbcount + 1;
//                                        objectMap.put("cbaa", cbcount);
//                                        //用量
//                                        objectMap.put("standardCount",
//                                                detailDO1.getStandardCount());
//                                        proportion = detailDO1.getStandardCount()
//                                                .divide(totalAmount, BigDecimal.ROUND_HALF_UP)
//                                                .multiply(new BigDecimal("100"))
//                                                .setScale(2, BigDecimal.ROUND_HALF_UP);
//
//                                        objectMap.put("proportion", proportion);
//                                    }
//                                }
//                                objectMap.put("cbcount", cbcount);
//                                mapList.add(objectMap);
//                            }
//
//                        }
//                    }
//                }
//
//            }
//        }
        Map<Long,String> materialNameAndId = materielDOList.stream().collect(Collectors.toMap(MaterielDO::getId, MaterielDO::getName, (v1, v2) -> v1));

        //一层
        if (!ObjectUtils.isEmpty(bomDO)) {
            Map<String, Object> objectMap = new HashMap<>();
            objectMap.put("level", "外层");
            objectMap.put("cbcount1", 0);
            //原料名称
            objectMap.put("name1", materiel.getName());
            objectMap.put("proportion1", 0.00);
            mapList.add(objectMap);
        }
        //二层
//        bomDetailDOSOne.add(bomDetailDOSOne.get(1));
//        bomDetailDOSOne.add(bomDetailDOSOne.get(1));
        if (!ObjectUtils.isEmpty(bomDetailDOSOne)){
            int num = 1;
            Map<String, Object> objectMap = new HashMap<>();
            objectMap.put("level", "中层");
            for (int i = 0; i < bomDetailDOSOne.size(); i++) {
                for (MaterielDO materielDO : materielDOList) {
                    if (bomDetailDOSOne.get(i).getMaterielId().equals(materielDO.getId())) {
                        String name = "name";
                        String cbcount = "cbcount";
                        //原料名称
                        if (AslConstant.TWO.equals(bomDetailDOSOne.get(i).getMaterielType())){
                            objectMap.put(cbcount + num, 0);
                        }else {
                            objectMap.put(cbcount + num, 1);
                        }
                        objectMap.put(name + num, materielDO.getName());
                        proportion = bomDetailDOSOne.get(i).getStandardCount()
                                .divide(totalAmount, BigDecimal.ROUND_HALF_UP)
                                .multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
                        //比例
                        objectMap.put("proportion"+ num, proportion);
                        num = num+1;
                    }
                }
            }
            mapList.add(objectMap);
        }
//        twoBomDOS = new ArrayList<BomDO>();
//        BomDO bomDO1 = new BomDO();
//        BomDO bomDO2 = new BomDO();
//        BomDO bomDO3 = new BomDO();
//        bomDO1.setMaterielId(270l);
//        bomDO2.setMaterielId(270l);
//        bomDO3.setMaterielId(270l);
//        twoBomDOS.add(bomDO1);
//        twoBomDOS.add(bomDO2);
//        twoBomDOS.add(bomDO3);
        //三层
        if (!CollectionUtils.isEmpty(twoBomDOS)) {
            Map<Long,BigDecimal> bomDetailDOSTwoAndCount = bomDetailDOSTwo.stream().collect(Collectors.toMap(BomDetailDO::getBomId, BomDetailDO::getStandardCount, (v1, v2) -> v1));
            int num = 1;
            Map<String, Object> threeMap = new HashMap<>();
            threeMap.put("level", "内层");
            for (int i = 0; i < twoBomDOS.size(); i++) {
                BomDO bomOne = twoBomDOS.get(i);
                threeMap.put("name" + num, materialNameAndId.get(bomOne.getMaterielId()));
                threeMap.put("cbcount" + num, 0);
                proportion = bomDetailDOSTwoAndCount.get(bomOne.getId())
                        .divide(totalAmount, BigDecimal.ROUND_HALF_UP)
                        .multiply(new BigDecimal("100"))
                        .setScale(2, BigDecimal.ROUND_HALF_UP);

                threeMap.put("proportion"+ num, proportion);
                num = num+1;
            }
            mapList.add(threeMap);
        }


        Map<String,Object> map1 = new HashMap<>();
        map1.put("bomList",mapList);
        map1.put("ylcount",mapList.size());
        map.put("bom",map1);
        map.put("bomNo",bomDO.getSerialno());
        return map;
    }
    @Override
    public Integer update(MoldingProductionInstructionDO entity) {
        return dao.update(entity);
    }

    @Override
    public int batchRemove(Long[] ids) {
        return dao.batchRemove(ids);
    }

    @Override
    public int remove(Long id) {
        return dao.remove(id);
    }

    @Override
    public int countForMap(Map<String, Object> params) {
        return dao.countForMap(params);
    }

    @Override
    public List<Long> getPlanIds() {
        return dao.getPlanIds();
    }

    @Override
    public List<MoldingProductionInstructionDO> list(Map<String, Object> map) {
        return dao.list(map);
    }

    @Override
    public List<Map<String, Object>> listForMap(Map<String, Object> param) {
        return dao.listForMap(param);
    }
}
